<html>
  <head>
    <meta charset='utf-8' />
    <title>My Pen</title>
  </head>
  <style>
canvas {
  float: left;
}
        form {
          float: left;
          width: 100px;
        }
        .param {
          float: left;
          width: 40px;
          height: 40px;
          margin-left: 5px;
        }
        .pen {
          border-radius: 20px;
        }
  </style>
  <script>
g=function(s){
  var s0=s[0];
  var s1 = s.substr(1);
  var r;
  switch(s0){
    case '#':// id
      r = document.getElementById(s1);
      break;
    case '.':// class name
      r = document.getElementsByClassName(s1);
      break;
    case '<':// tag name
      r = document.getElementsByTagName(s1);
      break;
    case '$':// name
      r = document.getElementsByName(s1);
      break;
    default:
      console.error('unknown symbol: ' + s0);
      console.trace();
  }
  return r;
};
openURL=function(url){//when window.open fails
  var a=document.createElement('a');
  a.href=url; a.target='_blank'; a.download='paper.png'
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
};
rwColor=function(c,s){//random walk wrt color
  var r='#';
  var n=0;
  for(var i=1; i<=5; i+=2){
    n=parseInt(c.substr(i,2),16);
    n+=(Math.random()<0.5 ? -1 : 1) * colorfulStep + 256;
    n%=256;
    r+= ( n<0x10? '0' : '' ) + n.toString(16);
  }
  return r;
};
  </script>
  <body>
    <canvas id='canvas'>no canvas</canvas>
    <form>
      <input id='pen-color' class='pen param' type='color' value='#000000' onchange='ctx.strokeStyle=this.value;'>
      <input id='pen-width' class='pen param' type='number' min='1' max='99' value='5' onchange='ctx.lineWidth=this.value;'>
      <br />
      <input id='pen-is-colorful' class='pen param' type='checkbox' checked='true' onchange='isColorful=this.checked;'>
      <input id='pen-colorful-step' class='pen param' type='number' min='1' max='99' value='7' onchange='colorfulStep=this.value;'>
      <br />
      <br />
      <br />
      <br />
      <hr />
      <input id='undo' class='param' type='button' value='<' onclick='iImg=(iImg-1+nImg)%nImg;ctx.putImageData(imgs[iImg],0,0);'>
      <input id='save' class='param' type='button' value='@' onclick='openURL(cvs.toDataURL());'>
    </form>
    <script>
cvs=g('#canvas');
cvs.width=cvs.parentElement.clientWidth-cvs.offsetLeft*2-100;
cvs.height=cvs.parentElement.clientHeight-cvs.offsetTop*2;

ctx=cvs.getContext('2d');

//// draw it!

drawing=false;

isColorful=g('#pen-is-colorful').checked;
colorfulStep=g('#pen-colorful-step').value;
lastPoint={}; recordLastPoint=function(p){ lastPoint.x=p.clientX; lastPoint.y=p.clientY; };

iImg=0;
nImg=9;//record only the last nImg imgs
imgs=new Array(nImg);
for(var i=0; i<nImg; i++){
  imgs[i]=ctx.getImageData(0,0,cvs.width,cvs.height);
}

isTouch=document.body.ontouchstart!==undefined;
cvs.addEventListener(isTouch ? 'touchstart' : 'pointerdown',
    function(event){
      ctx.beginPath();
      var p = isTouch ? event.touches[0] : event;
      ctx.moveTo(p.clientX, p.clientY);
      drawing=true;
      if(isColorful){
        recordLastPoint(p);
      }
      imgs[iImg++]=ctx.getImageData(0,0,cvs.width,cvs.height); iImg%=nImg;
    },
    false);
cvs.addEventListener(isTouch ? 'touchmove' : 'pointermove',
    function(event){
      if(drawing){
        var p = isTouch ? event.touches[0] : event;
        if(isColorful){
          ctx.beginPath();
          ctx.moveTo(lastPoint.x, lastPoint.y);
          recordLastPoint(p);
          g('#pen-color').value=rwColor(g('#pen-color').value, g('#pen-colorful-step').value);
          ctx.strokeStyle=g('#pen-color').value;
        }
        ctx.lineTo(p.clientX, p.clientY);
        ctx.stroke();
      }
    },
    false);
cvs.addEventListener(isTouch ? 'touchend' : 'pointerup',
    function(event){
      drawing=false;
    },
    false);

ctx.lineWidth=1;
ctx.strokeRect(0,0,cvs.width,cvs.height);
ctx.lineCap='round';

ctx.lineWidth=g('#pen-width').value;
    </script>
  </body>
</html>

